// JavaScript Document
String.prototype.format = function() {
	var formatted = this;
	for (var i = 0; i < arguments.length; i++) {
		var regexp = new RegExp('\\{'+i+'\\}', 'gi');
		formatted = formatted.replace(regexp, arguments[i]);
	}
	return formatted;
};

var moe = {
indexOf: function(array, elem) {
	if (array.indexOf)
		return array.indexOf(elem);
	else
		for (var i = 0, length = array.length; i < length; i++ )
			if (array[i] === elem)
				return i;
	return -1;	
},
config : null,
jsonData : null,
childrenCount : null,
searchAction : null,
collectAction : null,
deleteAction : null,
taglist : [],
currentTags: [],
tagClass : {0: "tag-type-general", 1: "tag-type-artist", 6: "tag-type-faults", 3: "tag-type-copyright", 4: "tag-type-character", 5: "tag-type-circle"},
tagType : {99: "All", 0: "General", 1: "Artist", 6: "Faults", 3: "Copyright", 4: "Character", 5: "Circle"},
rating : {"s":"Safe", "e":"Explicit", "q":"Questionable"},
digit_grouping: function (nStr){  
    nStr += '';  
    x = nStr.split('.');  
    x1 = x[0];  
    x2 = x.length > 1 ? '.' + x[1] : '';  
    var rgx = /(\d+)(\d{3})/;  
    while (rgx.test(x1)) {  
        x1 = x1.replace(rgx, '$1' + ',' + '$2');  
    }  
    return x1 + x2;  
},
highlight_posts_with_tag: function(tag) {
	$.each(moe.jsonData.posts, function(k, v) {
		if(tag && v.tags.indexOf(tag) != -1)
			thumb = $('#' + v.id).addClass("shadow-white");
		else
			thumb = $('#' + v.id).removeClass("shadow-white");
	});
},
tagTab: function(tagType) {
	var showTagType = [], allTypes = [0, 1, 3, 4, 5, 6];
	$('#tag-filter>li#' + moe.tagType[tagType] + '>a').toggleClass('selected');
	if (tagType == 99) {
		$('#tag-filter>li>a').removeClass('selected');
		$('#tag-filter>li#All>a').addClass('selected');
		showTagType = allTypes;
	}
	else {
		$('#tag-filter>li#All>a').removeClass('selected');
		for (var i = 0; i < 7; i++) { //okay js obj no bulitin length
			if ($('#tag-filter>li#' + moe.tagType[i] + '>a').attr('class') == 'selected')
				showTagType.push(i);
			else
				showTagType = jQuery.grep(showTagType, function(value) {return value != i;});
		}
	}
	if ($(showTagType).not(allTypes).get().length == 0 && $(allTypes).not(showTagType).get().length == 0) {
		$('#tag-filter>li>a').removeClass('selected');
		$('#tag-filter>li#All>a').addClass('selected');
		tagType = 99;
	}
	var title = '';
	if (tagType == 99)
		title = 'All';
	else {
		$.each(showTagType, function (k, v) {
			title += moe.tagType[v] + ', ';
		});
		title = title.slice(0, -2);
	}
	$('#tag>#tag-toggle>#filter>a').html('<h6>' + title + '</h6>');
	var $ul = $('#tag-sidebar');
	$ul.empty();
	for (var i in moe.currentTags) {
		var name = moe.currentTags[i][0], count = moe.currentTags[i][1], type = moe.currentTags[i][2];
		if (tagType == null || moe.indexOf(showTagType, type) != -1) {
			var $li = $('<li></li>', {'class' : moe.tagClass[type]});
			$li.append('<a href="#action={4}&tags={0}" onmouseover=\'moe.highlight_posts_with_tag("{2}")\' onmouseout=\'moe.highlight_posts_with_tag(null)\'><span class="tag-type">{1}:</span>{2}<span class="post-count">{3}</span></a>'
					.format(encodeURIComponent('eq ' + name), 
							moe.tagType[type], name, 
							moe.digit_grouping(count), 
							moe.searchAction));
			$li.appendTo($ul);
		}
	}
	//$ul.height($(window).height() - $('.navigation').outerHeight(true) - $('#search').outerHeight(true) - $('#tag-toggle').outerHeight(true) - 18);
	
},
cssHack : function() {
	//checkbox
	$('#search_form').find(':checkbox').css('border-width', 0);
},
/*
 * initSidebar
 *
 */
initSidebar : function() {
	var unfoldedCound = 0,
		accordion = $("#search .ss-accordion").accordion({
			header: 'h3',
			collapsible: true,
			autoHeight: false,
			active:false,
			animation: 'slide',
			change: function(event, ui) {
				if ($(this).accordion("option", "active") === false) {
					//folded
					unfoldedCound--;
					if (unfoldedCound === accordion.length - 1) {
						$('#search .ss-title .ui-icon').toggleClass('ui-icon-plusthick ui-icon-minusthick');
					}
				} else {
					//unfolded
					unfoldedCound++;
					if (unfoldedCound === accordion.length) {
						$('#search .ss-title .ui-icon').toggleClass('ui-icon-plusthick ui-icon-minusthick');
					}
				}
			}
		});
	/*
	 * init form status
	 */
	/*$('#search_form').find('select').each(function() {
		if (this.name.match(/^.+_operate.*$/)) {
			$(this).change(function() {
				if (this.options[this.selectedIndex].value === 'none') {
					$(this).next().attr("disabled", true);
				} else {
					$(this).next().attr("disabled", false);
				}
			});
			if (this.options[this.selectedIndex].value === 'none') {
				$(this).next().attr("disabled", true);
			}
		}
	});*/
	/*
	 * unfolded interaction
	 */
	$('#search .ss-title').click(function() {
		if (unfoldedCound === accordion.length) {
			//folded
			accordion.each(function() {
				if ($(this).accordion("option", "active") === 0)
					$(this).accordion("option", "active", false);
			});
		} else {
			//unfolded
			accordion.each(function() {
				if ($(this).accordion("option", "active") === false)
					$(this).accordion("option", "active", 0);
			});
		}
		return false;
	});
	/*
	 * form verify bind
	 */
	$('#search_form :input')
		.blur(function() {
			var $this = $(this);
			if (!$this.is('[allowed]')) {
				$('#search_form').data('valid', true);
				return;
			}
			//verify 
			var verify = true,
				ex = $this.attr('allowed').split('||');
			if (ex.length == 2) {
				var val = $this.val();
				if (val !== "" && !(new RegExp(ex[1], 'i')).test(val)) {
					//verify fail
					//feedback
					verify = 'Invalid value: ' + val;
					moe.notice.msg(verify);
					var that = this;
					setTimeout(function() {
						$(that).focus();
						that.select();
					}, 0);
				}
			}
			$('#search_form').data('valid', verify);
		})
		.filter(':text, textarea')
		.keydown(function(event) {
			//submit
			event.stopPropagation();
			if (event.which !== 13/*Enter*/) {
				return;
			}
			$(this).blur();
			$('#search_form').submit();
		})
		.end()
		.filter('[allowed]')
		.keypress(function(event) {
			//verify
			var ex = $(this).attr('allowed').split('||');
			if (ex.length != 2) {
				return;
			}
			var code = event.which;
			//Tab, Backspace key etc
			if (code === 0/*Tab*/ || code === 8/*Backspace*/ || event.ctrlKey || event.altKey) {
				return;
			}
			var key = String.fromCharCode(code);
			if(!(new RegExp(ex[0], 'i')).test(key)) {
				return false;
			}
		});
	var collectToList = function(query) {
			var url = 'http://' + window.location.host + '/json?' + query;
			window.location = url;
			return false;
		},
		collectToDir = function(query) {
			var url = 'http://' + window.location.host + '/json?' + query;
			moe.notice.msg('collecting');
			$.get(url, {},
				function(data) {
					var msg;
					if (data == 'success') {
						msg = 'Posts collected successful';
					} else {
						msg = 'Posts collected failed - ' + data;
					}
					moe.notice.msg(msg);
				});
			return false;
		};
	/*
	 * form submit bind
	 */
	$('#search_form').submit(function() {
		try{
			var $this = $(this),
				valid = $this.data('valid');
			if (valid !== true && valid) {
				moe.notice.msg('Form verify fail!<br/>Cause: ' + valid);
				return false;
			}
			
			//create query string
			var query = {};
			$this.find(':input').each(function() {
				var $this = $(this),
					name = $this.attr('name'),
					value = $this.val();
				value = $.trim(value);
				if (name in query) {
					return;
				}
				//special case
				if ($this.is('input[type="checkbox"]')) {
					if (this.checked) {
						query[name] = value;
					}
					return;
				}
				if (name.search(/_operate/) != -1) {//has operate
					var arr = name.split('_operate');
					name = arr[0] + arr[1];
					var nextValue = $this.next('[name="' + name + '"]').val();
					if (value === 'none' || nextValue === '') {//ignore
						return;
					}
					value = value + ' ' + nextValue;
					query[name] = value;
				} else {//not operate
					if (value === '' || value === 'none') {
						return;	
					}
					var prev = $this.prev('[name="' + name.replace(/(_\d+)?$/, '_operate$1') + '"]');
					if (prev.length > 0) {//prev has operate
						var preValue = prev.val();
						if (preValue === 'none') {
							return;
						}
						value = preValue + ' ' + value;
						query[name] = value;
					} else {
						query[name] = value;
					}
				}
			});
			var queryArray = [], value, collect, 
				action = 'searchPosts';
			for (var name in query) {
				value = query[name];
				if (name.search(/_\d+$/) != -1) {
					name = name.replace(/_\d+$/, '');
				}
				if (name === 'collect') {
					collect = value;
				} else if (name === 'action') {
					if (value.indexOf('Pool') >= 0) {
						value = 'searchPool';
					} else if (value.indexOf('Collections') >= 0) {
						value = 'searchCollections';
					} else {
						value = action;
					}
				} else if (name === 'pool') {
					action = 'searchPool';
				}
				name = encodeURIComponent(name);
				value = encodeURIComponent(value);
				queryArray.push(name + '=' + value);
			}
			if (queryArray.length <= 0) {//not query
				return false;	
			}
			//queryArray.push('action=' + action);
			query = queryArray.join('&');
			//log(query);
			
			if (collect) {
				var answer = window.confirm('Are you sure collect those posts: ' + query);
				if (!answer) {
					return false;
				}
				if (collect === 'list') {
					return collectToList(query);
				} else if (collect === 'directory') {
					return collectToDir(query);
				}
			}
			//ajax
			moe.loadContent(query);
		} catch(e) {
			//console.log('Form submit error: ' + e.message);
		}
		return false;
	});
	/*
	 * submit button bind
	 */
	$('#search .ss-submit')
		.hover(function() {
			$(this).toggleClass('ui-state-hover');
		}, 
		function() {
			$(this).toggleClass('ui-state-hover');
		})
		.click(function(event) {
			if (event.detail > 1) {
				return;
			}
			$('#search_form').submit();
			return false;
		});
	$('#search .ss-reset')
		.hover(function() {
			$(this).toggleClass('ui-state-hover');
		}, 
		function() {
			$(this).toggleClass('ui-state-hover');
		})
		.click(function(event) {
			$('#search_form')[0].reset();
			return false;
		});
	/*
	 * tag autocomplete
	 * extends $.ui.autocomplete
	 */
	$.widget( "custom.tagcomplete", $.ui.autocomplete, {
		_renderItem: function( ul, item) {
			var input = this.element.val(),
				label = item.label,
				index = input.lastIndexOf(' '),
				itemLabel = $('<a></a>'),
				strArray = [];
			
			if (index != -1) {
				input = input.substring(index + 1);
			}
			index = label.indexOf(input)
			
			strArray.push('<span class="' + moe.tagClass[item.type] + '">');
			strArray.push(label.substring(0, index));
			strArray.push('<span style="font-weight:bold;">');
			strArray.push(input);
			strArray.push('</span>');
			strArray.push(label.substring(index + input.length));
			strArray.push('</span><span class="post-count" style="float:right;font-style:italic;">');
			strArray.push(moe.digit_grouping(item.count));
			strArray.push('</span>');
			
			itemLabel.append(strArray.join(''));
			return $( "<li></li>" )
				.data( "item.autocomplete", item )
				.append( itemLabel )
				.appendTo( ul );
		}
	});
	$('#search_form .ss-tags').tagcomplete({
		delay: 300,
		//appendTo: '#search_form',
		appendTo: 'body',
		source: function(request, response) {
			var term = request.term, 
				index = term.lastIndexOf(' '),
				prefix;
			if (index != -1) {
				prefix = term.substring(0, index + 1);
				term = term.substring(index + 1);
			}
			this.element.data('prefix', prefix);
			if (term === '') {
				return;
			}
			$.getJSON(
				'http://' + window.location.host + '/json?action=tagTips&tags=' + encodeURIComponent(term), 
				function(data) {
					response(data.tagTips);
				}
			);
		},
		focus: function(event, ui){
			var value = ui.item.value,
				prefix = $(this).data('prefix');
			if (prefix) {
				value = prefix + value;
			}
			this.value = value;
			return false;
		},
		select: function(event, ui) {
			var value = ui.item.value,
				prefix = $(this).data('prefix');
			if (prefix) {
				value = prefix + value;
			}
			this.value = value;
			return false;
		}
	});
	//initSidbar function end
},
/*
 * initPreview
 *
 */
initPreview : function() {
	var timeout,
		$document = $(document),
		$window = $(window),
		$toolbar = $('<div></div>'),
		$preview = $('<div></div>', {'class' : 'preview shadow-grey'}),
		$deleteButton = $('<button class="iv-delete" title="Delete"></button>')
			.button({
				text: false,
				icons: {primary:'ui-icon-trash'}
			})
			.click(function(){
				var id = $preview.find('img').attr('id'),
					url = 'http://' + window.location.host + '/json',
					answer = window.confirm('Are you sure delete the collection(id:' + id + ')?');
				if (!answer) {
					return false;
				}
				
				$.get(url, 
					{'action' : moe.deleteAction, 'id' : id},
					function(data) {
						var msg;
						if (data == 'success') {
							msg = 'Collection(id : ' + id + ') deleted successful';
							$('#posts li #' + id).parent().remove();
							clear();
						} else {
							msg = 'Collection(id : ' + id + ') deleted failed';
						}
						moe.notice.msg(msg);
					});
				$(this).blur();
				return false;
			}),
		getFileSize = function(post) {
			var size = post.fileSize;
			if (size > 1048576) {
				size = (size / 1048576).toFixed(1);
				size += ' MB';
			} else {
				size = (size / 1024).toFixed(0);
				size += ' KB';
			}
			var result = '({0} {1})'.format(size, post.fileUrl.substring(post.fileUrl.lastIndexOf('.') + 1).toUpperCase());
			return result;
		},
		getTags = function(post) {
			var tags = post.tags.split(' '), result = '';
			$.each(tags, function(i, tag) {
				var label = tag, maxLength = 18, count = moe.taglist[tag][0], type = moe.taglist[tag][1];
				if (tag.length > maxLength) {
					label = tag.substr(0, maxLength) + '...';
				}
				result += '<span class="{1}-preview"><a href="#action={5}&tags={4}"><span class="tag-type">{2}:</span>{3}<span class="post-count">{0}</span></a> </span>'
					.format(moe.digit_grouping(count), 
							moe.tagClass[type], 
							moe.tagType[type], 
							tag, 
							encodeURIComponent('eq ' + tag),
							moe.searchAction);
				if (i > maxLength) {
					result += '<span class="post-count">and ' + (tags.length - maxLength) + ' more</span>';
					return false;
				}
			});
			return result;
		},
		getInfo = function(id) {
			var post = moe.getPostById(id),
				result;
			result = ('<span class="stats-description-preview">Id: {0}</span>' +
				'<a title="Search posts with the same width" style="color: black;" href="#action={7}&width=eq {1}"><u>{1}</u></a> ' +
				'<a title="search posts with the same size" style="color: black;" href="#action={7}&width=eq {1}&height=eq {2}">x</a> ' +
				'<a title="search posts with the same height" style="color: black;" href="#action={7}&height=eq {2}"><u>{2}</u></a>' +
				'<span style="margin-left: 5px;" class="stats-description-preview">{3}</span><br />' +
				'<span class="stats-description-preview">Rating:</span>{4}' +
				'<span style="margin-left: 10px;" class="stats-description-preview">Score:</span>{5}<br />' +
				'<span class="tag-preview"><span class="stats-description-preview">Tags:</span>{6}</span>')
					.format(moe.digit_grouping(post.id), 
							post.width, 
							post.height, 
							getFileSize(post), 
							moe.rating[post.rating], 
							post.score, 
							getTags(post),
							moe.searchAction);
			return result;
		},
		togglePreviewZoom = function($img) {
			var xoffset, yoffset,
				$previewImage, 
				left, top,
				imgWidth, imgHeight,
				previewWidth, previewHeight,
				id = $img.attr('id'), contentMargin = 6, minWidth = 150, maxSize = 300;
			$preview
				.append('<p style = "text-align:center;">' +
						'<img id = "' + id + '" src = "' + $img.attr('src') + '" class = "zoom-disable viewable"/></p>' +
						'<p>' + getInfo(id) + '</p>')
				.appendTo($img.parents('ul'));
			$previewImage = $preview.find('img');
			imgWidth = $previewImage.width();
			imgHeight = $previewImage.height();
			
			if (imgWidth > maxSize || imgHeight > maxSize) {
				if (imgWidth > imgHeight) {
					imgHeight = imgHeight * maxSize / imgWidth;
					imgWidth = maxSize;
				} else {
					imgWidth = imgWidth * maxSize / imgHeight;
					imgHeight = maxSize;
				}
				$previewImage.width(imgWidth);
				$previewImage.height(imgHeight);
			}
			
			xoffset = imgWidth - $img.width();
			yoffset = imgHeight - $img.height();
			
			previewWidth = imgWidth + contentMargin * 2;
			if (previewWidth < minWidth) {
				previewWidth = minWidth;
				xoffset += previewWidth - imgWidth - contentMargin * 2;
			}
			$preview.width(previewWidth);
			previewWidth = $preview.width();
			previewHeight = $preview.height();
			
			left = $img.offset().left - $document.scrollLeft() - contentMargin - (xoffset / 2);
			top = $img.offset().top - $document.scrollTop() - contentMargin - (yoffset / 2);
			
			if (top < 0) {
				top = 0;
			} else if (top + previewHeight > $window.height()) {
				top = $window.height() - previewHeight;
			}
			if (left < 0) {
				left = 0;
			} else if (left + previewWidth > $window.width()) {
				left = $window.width() - previewWidth;
			}
			
			$preview
				.css({
					'top' : top,
					'left' : left
				})
				.mouseleave(function(event) {
					if ($toolbar.has(event.relatedTarget).size() > 0) {
						return;
					}
					clear();
				});
				
			if ($toolbar.children().size() < 1) {
				initToolbar();
			}
			$toolbar
				.appendTo($img.parents('ul'))
				.css({
					'opacity' : 0, 
					'filter': 'alpha(opacity=0)',
					'left' : $previewImage.offset().left - $document.scrollLeft(),
					'top' : $previewImage.offset().top - $document.scrollTop()
				});
			toggleDeleteButton();
			//togglePreviewZoom function end
		},
		clear = function() {
			if ($preview.children().size() < 1) {
				return;
			}
			$preview
				.css({'width' : 'auto', 'height' : 'auto'})
				.empty()
				.detach();
			$toolbar.detach();
		},
		initToolbar = function() {
			$toolbar
				.css({
					 'position': 'fixed'
				})
				.append('<button class="iv-collect" title="Collect"></button>' +
						'<button class="iv-newwin" title="New Window"></button>')
				.mouseover(function(event){
					$toolbar.css({
					 	'opacity' : 0.7, 
					 	'filter': 'alpha(opacity=70)'
					});
				})
				.mouseleave(function(event) {
					if ($preview.get(0) === event.relatedTarget 
							|| $preview.has(event.relatedTarget).size() > 0) {
						$toolbar.css({
							'opacity' : 0, 
							'filter': 'alpha(opacity=0)'
						});
						return;
					}
					//clear();
				})
				.find('.iv-collect')
				.button({
					text: false,
					icons: {primary:'ui-icon-folder-collapsed'}
				})
				.click(function() {
					var id = $preview.find('img').attr('id'),
						url = 'http://' + window.location.host + '/json';
					$.get(url, 
						{'action' : moe.collectAction, 'id' : id},
						function(data) {
							var msg;
							if (data == 'success') {
								msg = 'Post(id : ' + id + ') collected successful';
							} else {
								msg = 'Post(id : ' + id + ') collected failed - ' + data;
							}
							moe.notice.msg(msg);
						});
					$(this).blur();
					return false;
				})
				.end()
				.find('.iv-newwin')
				.button({
					text: false,
					icons: {primary:'ui-icon-newwin'}
				})
				.click(function() {
					var post = moe.getPostById($preview.find('img').attr('id'));
					window.open('http://' + window.location.host + post.fileUrl);
					$(this).blur();
					return false;
				});
			$toolbar.append($deleteButton);
		},
		toggleDeleteButton = function(){
			if (moe.deleteAction === null) {
				$deleteButton.hide();
			} else {
				$deleteButton.show();
			}
			
		};
	/*
	 * bind zoom
	 */
	$('.post-img img')
		.live('mouseenter', function() {
			$(this).addClass('shadow-white');
		})
		.live('mousemove', function() {
			if (timeout) {
				clearTimeout(timeout);
				timeout = null;
			}
			var that = this;
			timeout = setTimeout(function() {
				clear();
				togglePreviewZoom($(that));
			}, 200);
		})
		.live('mouseleave', function() {
			if (timeout) {
				clearTimeout(timeout);
			}
			timeout = null;
			$(this).removeClass('shadow-white');
		});

	//initPreview function end
},
/*
 * initSidebarSlip
 *
 */
initSidebarSlip : function() {
	var sidebarWidth = 230,
		$contentInner = $('#content-inner'),
		$sidebarSlip = $('#sidebar-slip'),
		refreshSidebarSlip = function() {
			$sidebarSlip.height($contentInner.height());
		};
		
	$sidebarSlip
		.hover(function(event) {
			var $this = $(this),
				$button = $this.find('.slip-button'), 
				scrollTop = $(document).scrollTop(),
				top;

			if ($this.offset().top + $this.height() < scrollTop) {
				top = 0;
			} else {
				top = event.clientY + scrollTop - $button.height() / 2;
			}
			if (top < $this.offset().top) {
				top = $this.offset().top;
			}
			if (top > 0) {
				$button.offset({
					top : top
				})
				.css('visibility', 'visible');
			}
			$this.css('border', '1px dashed #666666');
		}, function() {
			$(this)
				.css('border', '0px')
				.find('.slip-button')
				.css('visibility', 'hidden');
		})
		.find('.slip-button')
		.hover(function() {
			$(this).toggleClass('ui-state-hover');
		}, function() {
			$(this).toggleClass('ui-state-hover');
		})
		.click(function() {
			var $sidebar = $('#sidebar'),
				$content = $('#content'),
				srcMarginLeft = parseInt($content.css('margin-left')),
				old = parseInt($sidebar.css('left'));
			if ($sidebar.css('display') !== 'none') {//hidden
				$sidebar.hide();
				$content.css('margin-left', srcMarginLeft - sidebarWidth);
				$sidebarSlip.find('span').toggleClass('ui-icon-triangle-1-e ui-icon-triangle-1-w');
			} else {//show
				$sidebar.show();
				$content.css('margin-left', srcMarginLeft + sidebarWidth);
				$sidebarSlip.find('span').toggleClass('ui-icon-triangle-1-e ui-icon-triangle-1-w');
			}
			$contentInner.trigger('resize.moe');
			return false;
		});
	//bind resize evnet
	$contentInner.bind('resize.moe', function() {
		refreshSidebarSlip();
	});
	$(window).resize(function() {
		refreshSidebarSlip();
	});
	//refreshSidebarSlip();
},
/*
 * initImageViewer
 *
 */
initImageViewer : function() {
	var getFileSize = function(post) {
			var size = post.fileSize;
			if (size > 1048576) {
				size = (size / 1048576).toFixed(1);
				size += 'MB';
			} else {
				size = (size / 1024).toFixed(0);
				size += 'KB';
			}
			var result = result = size + ' ' + post.fileUrl.substring(post.fileUrl.lastIndexOf('.') + 1).toUpperCase();
			return result;
		},
		getSource = function(post) {
			var source = post.source;
			if (source == '') {
				return '';
			} else {
				var tmp = '<li><span class="stats-description">Source:</span>';
				if (source.indexOf('http://') === 0 || source.indexOf('https://') === 0) {
					tmp += '<a href="' + source + '" target="_blank">' + source + '</a>';
				} else {
					tmp += source
				}
				source = tmp += '</li>';
			}
			return source;
		},
		getParent = function(post) {
			var parentId = post.parentId;
			if (parentId != 0)
				return ('<li><span class="stats-description">Parent:</span>' +
					'<a href="#action={2}&id={1}">{0}</a></li>')
						.format(parentId, 
								encodeURIComponent('eq ' + parentId), 
								moe.searchAction);
			else
				return '';
		},
		getTags = function(post) {
			var tags = post.tags.split(' '), result = '';
			$.each(tags, function(i, tag) {
				var taglistObj = moe.taglist[tag],
					count = taglistObj ? taglistObj[0] : '?', 
					type = taglistObj ? taglistObj[1] : 0;
				tags[i] = [tag, count, type];
			});
			tags.sort(function (a, b){return a[2] - b[2];});
			$.each(tags, function(i, tag) {
				result += ('<span class="{1}-preview"><a href="#action={5}&tags={4}">' +
					'<span class="tag-type">{2}:</span>{3}<span class="post-count">{0}</span></a> </span>')
						.format(tag[1], 
								moe.tagClass[tag[2]], 
								moe.tagType[tag[2]], 
								tag[0], 
								encodeURIComponent('eq ' + tag[0]),
								moe.searchAction);
			});
			return result;
		},
		getChildren = function(post) {
			var result = '', count;
			if (post.hasChildren) {
				count = moe.childrenCount[post.id];
				count = count ? count : '?';
				result = ('<li><span class="stats-description">Children: </span>' +
					'<a href="#action={2}&parent_id={0}">{1}</a></li>')
						.format(post.id,
								count,
								moe.searchAction);
			}
			return result;
		},
		createZoomButton = function() {
			$('.iv-toolbar .iv-zoom').button({
				text: false,
				icons: {primary:'ui-icon-zoomin'}
			})
			.click(function() {// zoom tool
				//status check
				var $img = $('.iv-content img'),
					$imgParent = $img.parent();
				if ($img.width() > $imgParent.width() 
						|| $img.height() > $imgParent.height()) {
					$img.removeClass('iv-zoomin').addClass('iv-zoomout');
				} else {
					$img.removeClass('iv-zoomout').addClass('iv-zoomin');
				}
				$img
					.unbind('mousedown')
					.removeClass('iv-dragready iv-dragstart')
					.mousedown(function(event) {
						if (event.which !== 1) {// left button
							return;
						}
						var $this = $(this);
						if ($this.is('.iv-zoomin')) {//zoom in
							var xoffset = event.clientX + $(document).scrollLeft() - $this.offset().left,
								yoffset = event.clientY + $(document).scrollTop() - $this.offset().top,
								referWidth, referHeight,
								scrollLeft, scrollTop;
											
							referWidth = $this.width();
							referHeight = $this.height();
							$this.css({
								'width' : 'auto',
								'height' : 'auto'
							});
							scrollLeft = xoffset * $this.width() / referWidth - $('.iv-content').width() / 2;
							scrollTop = yoffset * $this.height() / referHeight - $('.iv-content').height() / 2;
									
							$('.iv-content').scrollLeft(scrollLeft).scrollTop(scrollTop);
						} else {//zoom out
							var $this = $(this),
								$imageViewer = $('#image-viewer'),
								$imageViewerParent = $imageViewer.parent('.ui-dialog'),
								parentPadding = parseInt($imageViewerParent.css('padding-bottom')) + parseInt($imageViewerParent.css('padding-top')),
								contentHeight = $imageViewer.height() - $imageViewer.find('.iv-info').outerHeight(true) - parentPadding,
								contentWidth = $imageViewer.width(),
								imgWidth, imgHeight;
							if ($this.width() / $this.height() > contentWidth / contentHeight) {
								imgWidth = contentWidth;
								imgHeight = Math.floor(contentWidth * $this.height() / $this.width());
							} else {
								imgWidth = Math.floor(contentHeight * $this.width() / $this.height());
								imgHeight = contentHeight;
							}
							$this.width(imgWidth).height(imgHeight);
						}
						$this.toggleClass('iv-zoomin iv-zoomout');
						imageViewer.trigger('resize.moe');
					});
				return false;
			});
		},
		createDragButton = function() {
			var x, y,
				index = 0,
				sample = 1,
				rate = 1;
				
			$('.iv-toolbar .iv-drag').button({
				text: false,
				icons: {primary:'ui-icon-arrow-4'}
			})
			.click(function() {// drag tool
				$('.iv-content img')
					.unbind('mousedown')
					.removeClass('iv-zoomin iv-zoomout')
					.addClass('iv-dragready')
					.mousedown(function(event) {// start drag
						if (event.which !== 1) {// only left button
							return;
						}
						x = event.clientX;
						y = event.clientY;
						
						$(this).addClass('iv-dragstart');
						return false;
					});
				return false;
			});
			$('.iv-content img')
				.live('mousemove', function(event) {
					var $this = $(this);
					if ($this.hasClass('iv-dragstart') && index++ % sample === 0) {
						var xoffset = event.clientX - x,
							yoffset = event.clientY - y,
							top = $this.offset().top,
							left = $this.offset().left;
						
						top += yoffset * rate;
						left += xoffset * rate;
						$this.offset({
							'top' : top,
							'left' : left
						});
						
						x = event.clientX;
						y = event.clientY;
					}
					return false;
				})
				.live('mouseup', function() {
					$(this).removeClass('iv-dragstart');
					return false;
				})
				.live('mouseout', function(){
					$(this).removeClass('iv-dragstart');
					return false;
				});
		},
		createNewWindowButton = function() {
			$('.iv-toolbar .iv-newwin').button({
				text: false,
				icons: {primary:'ui-icon-newwin'}
			})
			.click(function() {
				window.open('http://' + window.location.host + $('.iv-content > *').attr('src'));
				return false;
			});
		},
		createCollectButton = function() {
			$('.iv-toolbar .iv-collect').button({
				text: false,
				icons: {primary:'ui-icon-folder-collapsed'}
			})
			.click(function() {
				var id = $('.iv-content > *').attr('id'),
					url = 'http://' + window.location.host + '/json';
				$.get(url, 
					{'action' : moe.collectAction, 'id' : id},
					function(data) {
						var msg;
						if (data == 'success') {
							msg = 'Post(id : ' + id + ') collected successful';
						} else {
							msg = 'Post(id : ' + id + ') collected failed - ' + data;
						}
						moe.notice.msg(msg);
					});
				return false;
			});
		},
		createDeleteButton = function(){
			$('.iv-toolbar .iv-delete').button({
				text: false,
				icons: {primary:'ui-icon-trash'}
			})
			.click(function(){
				var id = $('.iv-content > *').attr('id'),
					url = 'http://' + window.location.host + '/json',
					answer = window.confirm('Are you sure delete the collection(id:' + id + ')?');
				if (!answer) {
					return false;
				}
				$.get(url, 
					{'action' : moe.deleteAction, 'id' : id},
					function(data) {
						var msg;
						if (data == 'success') {
							msg = 'Collection(id : ' + id + ') deleted successful';
							$('#posts li #' + id).parent().remove();
						} else {
							msg = 'Collection(id : ' + id + ') deleted failed - ' + data;
						}
						moe.notice.msg(msg);
					});
				return false;
			});
		},
		eventSupported = function( eventName,el ) {
			el = el || document.createElement("div");
			eventName = "on" + eventName;
			var isSupported = (eventName in el);
			if (el.setAttribute && !isSupported ) {
				el.setAttribute(eventName, "return;");
				isSupported = typeof el[eventName] === "function";
			}
			el = null;
			return isSupported;
		},
		bindWheelEvent = function(obj, callback) {
			var type = eventSupported("mousewheel") ? "mousewheel":"DOMMouseScroll";
			$(obj).bind(type, function(event){
				var delta = 0, result;
				event = event.originalEvent;
				if (event.detail) {
					delta = -event.detail / 3;
				} else if (event.wheelDelta) {
					delta = event.wheelDelta / 28;
					//opera 9x系列的滚动方向与IE保持一致，10后修正
					if(window.opera && window.opera.version() < 10) {
						delta = -delta;
					}
				}
				//由于事件对象的原有属性是只读，只能通过添加一个私有属性delta来解决兼容问题，上滚为正，下滚为负
				event.delta =  Math.round(delta); //修正safari的浮点 bug
				result = callback.call(obj, event);
				if (!result) {
					event.preventDefault();
				}
				return result;
			});
		},
		initWheelListener = function(){
			var focus = {},
				wheelEventHandler = function(event){
					if (moe.config.zoom_rate === 0 || event.delta === 0) {
						return;
					}
					moe.config.zoom_rate = moe.config.zoom_rate || 2;
					
					var $imageViewer = $('#image-viewer'),
						$imageViewerParent = $imageViewer.parent('.ui-dialog'),
						parentPadding = parseInt($imageViewerParent.css('padding-bottom')) + parseInt($imageViewerParent.css('padding-top')),
						contentHeight = $imageViewer.height() - $imageViewer.find('.iv-info').outerHeight(true) - parentPadding,
						contentWidth = $imageViewer.width(),
						$target = $(event.target),
						id = $target.attr('id'),
						post = moe.getPostById(id),
						zoomRate = moe.config.zoom_rate * event.delta / -100,
						width = $target.width(),
						height = $target.height(),
						offsetWidth, offsetHeight;
					if (Math.abs(zoomRate) > 0.99) {
						zoomRate = zoomRate > 0 ? 0.99 : -0.99;
					}
					if (zoomRate < 0 
							&& width <= contentWidth && height <= contentHeight) {// zoom out
						return;
					} else if (zoomRate > 0 
							&& (width >= post.width || height >= post.height)) {// zoom in
						return;
					}
					
					offsetWidth = width * zoomRate;
					offsetHeight = height * zoomRate;
					width += offsetWidth;
					height += offsetHeight;
					
					if (zoomRate < 0) {// zoom out
						if (width <= contentWidth && height <= contentHeight) {
							if (width / height > contentWidth / contentHeight) {
								var newHeight = Math.floor(contentWidth * height / width);
								offsetHeight += newHeight - height;
								offsetWidth += contentWidth - width;
								height = newHeight;
								width = contentWidth;
							} else {
								var newWidth = Math.floor(contentHeight * width / height);
								offsetWidth += newWidth - width;
								offsetHeight += contentHeight - height;
								width = newWidth;
								height = contentHeight;
							}
						}
					} else {//zoom in
						if (width >= post.width) {
							offsetWidth -= width - post.width;
							offsetHeight -= height - post.height;
							width = post.width;
							height = post.height;
						}
					}
					if (width === $target.width()) {
						return;
					}
					
					var $document = $(document),
						top = $target.offset().top,
						left = $target.offset().left,
						offsetX = event.clientX - left + $document.scrollLeft(),
						offsetY = event.clientY - top + $document.scrollTop();						
					offsetWidth = offsetX * offsetWidth / $target.width();
					offsetHeight = offsetY * offsetHeight / $target.height();	
					top -= offsetHeight;
					left -= offsetWidth;
					
					$target.css({
						'width' : width, 
						'height' : height
					});
					$target.offset({
						'top' : top, 
						'left' : left
					});
					//imageViewer.trigger('resize.moe')
					return false;
				},
				$img = $('.iv-content img');
				
			bindWheelEvent($img.get(0), wheelEventHandler);
		},
		documentWheelSwitch = function(enable){
			var disableHandler = function(event){
					event.preventDefault();
					return false;
				},
				$document = $(document),
				type = eventSupported("mousewheel") ? "mousewheel.doc" : "DOMMouseScroll.doc";
			if (enable) {
				$document.unbind(type);
			} else {
				$document.bind(type, disableHandler);
			}
		},
		imageViewer = $('#image-viewer')
			.dialog({// create dialog
				autoOpen: false,
				modal: true,
				draggable: false,
				resizable: false,
				//show : 'fade',//Blind
				//hide : 'fade',
				zindex : 2000,
				title : '<div class="iv-toolbar">'
						+ '<button class="iv-zoom" title="Zoom"></button>'
						+ '<button class="iv-drag" title="Drag"></button>'
						+ '<button class="iv-collect" title="Collect"></button>'
						+ '<button class="iv-newwin" title="New Window"></button>'
						+ '<button class="iv-delete" title="Delete"></button>'
						+ '</div>',
				create : function() {
					//zoom
					createZoomButton();
					//drag
					createDragButton();
					//new window
					createNewWindowButton();
					//collect
					createCollectButton();
					//delete
					createDeleteButton();
					//imageViewer.hasClass('full-screen')
					$('.ui-dialog-titlebar').dblclick(function(){
						imageViewer.toggleClass('full-screen');
						resizeDialog();
						resizeView();
						return false;
					});
				},
				open : function(){
					documentWheelSwitch(false);
					$('.ui-widget-overlay').click(function() {
						if (imageViewer && imageViewer.dialog('isOpen')) {
							imageViewer.dialog('close')
						}
					});
					attachDeleteButton();
				},
				close : function() {// clear
					documentWheelSwitch(true);
					reset();
					if (imageViewer.hasClass('full-screen')) {
						$('body').css({'overflow' : 'auto'});
					}
				}
			}),
		reset = function() {
			imageViewer
				.find('.iv-content')
				.css('height', 'auto')
				.find('*')
				.empty()
				.remove()
				.end()
				.end()
				.find('.iv-info *')
				.empty()
				.remove();
				
			$('.iv-toolbar .iv-zoom').button( "enable" );
			$('.iv-toolbar .iv-drag').button( "enable" );
			$('.iv-toolbar .iv-collect').button( "enable" );
			$('.iv-toolbar .iv-newwin').button( "enable" );
			$('.iv-toolbar .iv-delete').button( "enable" );
		},
		resizeDialog = function() {
			var widthRatio = 19 / 20,
				heightRatio = 15 / 16,
				$window = $(window),
				position = 'center',
				dialogWidth, dialogHeight;
			if (imageViewer.hasClass('full-screen')) {
				widthRatio = heightRatio = 1;
				position = ['top', 'left'];
				$('body').css({'overflow' : 'hidden'});
			} else {
				$('body').css({'overflow' : 'auto'});
			}
			dialogWidth = Math.floor($window.width() * widthRatio),
			dialogHeight = Math.floor($window.height() * heightRatio);
			
			imageViewer.dialog('option', 'width', dialogWidth);
			imageViewer.dialog('option', 'height', dialogHeight);
			imageViewer.dialog("option", "position", position);
		},
		resizeView = function(post) {
			var $img = imageViewer.find('.iv-content > *'),
				parentPadding = parseInt(imageViewer.parent('.ui-dialog').css('padding-bottom')) + parseInt(imageViewer.parent('.ui-dialog').css('padding-top')),
				contentHeight = imageViewer.height() - imageViewer.find('.iv-info').outerHeight(true) - parentPadding,
				contentWidth = imageViewer.width(),
				imgWidth, imgHeight;
			post = post || moe.getPostById($img.attr('id'));
			//log(post.width + 'x' + post.height + ' ' + contentWidth + 'x' + contentHeight);
			if (post.width <= contentWidth && post.height <= contentHeight) {
				imgWidth = post.width;
				imgHeight = post.height;
					
				$('.iv-toolbar .iv-zoom').button( "disable" );
				$('.iv-toolbar .iv-drag').button( "disable" );
			} else if (post.width / post.height > contentWidth / contentHeight) {
				imgWidth = contentWidth;
				imgHeight = Math.floor(contentWidth * post.height / post.width);
				
				$('.iv-toolbar .iv-zoom').button( "enable" );
				$('.iv-toolbar .iv-drag').button( "enable" );
			} else {
				imgWidth = Math.floor(contentHeight * post.width / post.height);
				imgHeight = contentHeight;
				
				$('.iv-toolbar .iv-zoom').button( "enable" );
				$('.iv-toolbar .iv-drag').button( "enable" );
			}
			
			$img.parent().height(contentHeight);
			$img.css({
				'top' : 0,
				'left'  : 0
			});
			
			if (!$img.is('.iv-zoomout')) {
				$img.width(imgWidth).height(imgHeight);
			}
			//log(imgWidth + 'x' + imgHeight + ' ' + contentHeight);
			imageViewer.trigger('resize.moe');
		},
		render = function(post) {
			var $content,
				$ul = $('<ul></ul>')
					.append('<li><span class="stats-description">Id:</span>' + post.id + '</li>')
					.append(('<li><span class="stats-description">Size:</span>' +
							'<a title="Search posts with the same width" style="color: white;" href="#action={2}&width=eq {0}"><u>{0}</u></a> ' +
							'<a title="search posts with the same size" style="color: white;" href="#action={2}&width=eq {0}&height=eq {1}">x</a> ' +
							'<a title="search posts with the same height" style="color: white;" href="#action={2}&height=eq {1}"><u>{1}</u></a></li>')
								.format(post.width, 
										post.height,
										moe.searchAction))
					.append('<li><span class="stats-description">Rating:</span>' + moe.rating[post.rating] + '</li>')
					.append('<li><span class="stats-description">Score:</span>' + post.score + '</li>')
					.append('<li><span class="stats-description">File:</span>' + getFileSize(post) + '</li>')
					.append(getSource(post))
					.append(getParent(post))
					.append(getChildren(post))
					.append('<li><span class="stats-description">Tags:</span>' + getTags(post) + '</li>');
				
			if (post.fileUrl.indexOf('.swf') !== -1) {//flash
				$content = $('<object id="' + post.id + '" width="' + post.width + '" height="' + post.height + '" src="' + post.fileUrl + '">'
							+ '<param name="movie" value="' + post.fileUrl + '">'
							//+ '<param name="quality" value="high">'
							+ '<embed src="' + post.fileUrl + '" quality="high" type="application/x-shockwave-flash" width="' + post.width + '" height="' + post.height + '"> </embed>'
							+ '</object>');

				$('.iv-toolbar .iv-zoom').button( "disable" );
				$('.iv-toolbar .iv-drag').button( "disable" );
			} else {
				$content = $('<img />', {
						id : post.id,
						src : post.fileUrl/*,
						width : post.width,
						height : post.height*/
					});
				$content.error(function() {
						$(this)
							.before('<span id="' + $(this).attr('id') + '">' + post.fileUrl + ' Not Found!</span>')
							.remove();
						resizeView(post);
							
						$('.iv-toolbar .iv-zoom').button( "disable" );
						$('.iv-toolbar .iv-drag').button( "disable" );
						$('.iv-toolbar .iv-collect').button( "disable" );
						$('.iv-toolbar .iv-newwin').button( "disable" );
						$('.iv-toolbar .iv-delete').button( "disable" );
						return true;
					});
			}
			
			imageViewer
				.find('.iv-info')
				.append($ul);
			
			imageViewer
				.find('.iv-content')
				.append($content);
			
			resizeView(post);
			
			if (moe.config.zoom_rate === 0) {
				if (!$('.iv-toolbar .iv-zoom').button('option', 'disabled')) {
					$('.iv-toolbar .iv-zoom').click();
				}
			} else {
				if (!$('.iv-toolbar .iv-drag').button('option', 'disabled')) {
					$('.iv-toolbar .iv-drag').click();
				}
			}
			initWheelListener();
		},
		open = function(id) {
			var post = moe.getPostById(id);
			resizeDialog();
			imageViewer.dialog('open');
			render(post);
		},
		attachDeleteButton = function() {
			var $deleteButton = $('.iv-toolbar .iv-delete');
			if (moe.deleteAction === null) {
				$deleteButton.hide();
			} else {
				$deleteButton.show();
			}
		};
		
	//bind event
	imageViewer
		.find('.iv-info a')
		.live('click', function() {//bind tags link
			imageViewer.dialog('close');
		})
		.end()
		.parent()
		.bind('keydown', function(event) {
			if (event.which === 37) {//left arrow
				$('#iv-navigate-left').click();
				return false;
			} else if (event.which === 39) {//right arrow
				$('#iv-navigate-right').click();
				return false;
			}
			/*
			if (event.ctrlKey) {
				
			}*/
		});
	//
	//navigate button
	$('<div></div>', {
	  	'id' : 'iv-navigate-left', 
		'title' : 'Previous(←)',
		'class' : 'iv-navigate-placeholder'
		})
		.appendTo(imageViewer)
		.mouseenter(function() {
			$(this).toggleClass('iv-navigate-left-show iv-navigate-placeholder');
		})
		.mouseleave(function() {
			$(this).toggleClass('iv-navigate-left-show iv-navigate-placeholder');
		})
		.click(function() {
			var data = moe.jsonData,
				id = $('.iv-content > *').attr('id'),
				index;
			$.each(data.posts, function(i, post) {
				if (post.id == id) {
					index = i - 1;
					return false;
				}
			});
			if (index < 0) {
				if (!data.page.hasPrev) {
					return;
				}
				var query = moe.history.getToken();
				if (query.search(/page=\d+/) != -1) {
					query = query.replace(/page=\d+/, 'page=' + (data.page.current - 1));
				} else {
					query += '&page=' + (data.page.current - 1);
				}
				moe.overlay.create('#image-viewer');
				moe.loadContent(query, function(data) {
					moe.overlay.destroy();
					reset();
					render(data.posts[data.posts.length - 1]);
				});
			} else {
				reset();
				render(data.posts[index]);
			}
			return false;
		});
	$('<div></div>', {
	  	'id' : 'iv-navigate-right', 
		'title' : 'Next(→)',
		'class' : 'iv-navigate-placeholder'
		})
		.appendTo(imageViewer)
		.mouseenter(function() {
			$(this).toggleClass('iv-navigate-right-show iv-navigate-placeholder');
		})
		.mouseleave(function() {
			$(this).toggleClass('iv-navigate-right-show iv-navigate-placeholder');
		})
		.click(function() {
			var data = moe.jsonData,
				id = $('.iv-content > *').attr('id'),
				index;
			$.each(data.posts, function(i, post) {
				if (post.id == id) {
					index = i + 1;
					return false;
				}
			});
			if (index >= data.posts.length) {
				if (!data.page.hasNext) {
					return;
				}
				var query = moe.history.getToken();
				if (query.search(/page=\d+/) != -1) {
					query = query.replace(/page=\d+/, 'page=' + (data.page.current + 1));
				} else {
					query += '&page=' + (data.page.current + 1);
				}
				moe.overlay.create('#image-viewer');
				moe.loadContent(query, function(data) {
					moe.overlay.destroy();
					reset();
					render(data.posts[0]);
				});
			} else {
				reset();
				render(data.posts[index]);
			}
			return false;
		});
	//bind event
	imageViewer.bind('resize.moe', function() {
		var top = $('.iv-info').outerHeight(true) / 2 + imageViewer.height() / 2 - $('#iv-navigate-right').outerHeight(true) / 2,
			right = 0;
		if ($('.iv-content').height() < $('.iv-content img').height()) {
			right = 18;//scroll bar width
		}
		$('#iv-navigate-left')
			.css('left', '0px')
			.css('top', top);
		$('#iv-navigate-right')
			.css('right', right + 'px')
			.css('top', top);
	});
	//
	$(window).resize(function() {
		if (imageViewer && imageViewer.dialog('isOpen')) {
			resizeDialog();
			resizeView();
		}
	});
	
	$('#posts .viewable').live('click', function(event) {
		if (event.detail > 1 || imageViewer.dialog('isOpen')) {
			return false;
		}
		open($(this).attr('id'));
		return false;
	});
	//initImageViewer function end
},
/*
 * getPostById
 *
 */
getPostById : function(id) {
	var result;
	if (!moe.jsonData.posts) {
		return null;
	}
	$.each(moe.jsonData.posts, function(i, post) {
		if (id == post.id) {
			result = post;
			return false;
		}
	});
	return result;
	//getPostById function end
},
/*
 * renderContent
 *
 */
renderContent : function() {
	var $posts = $('#posts'),
		$page = $('#pagination'),
		pageData = moe.jsonData.page,
		fetchingTags = [];
		prepareTags = function() {
			$('#tag-sidebar').empty();
			moe.currentTags = [];
			var posts = moe.jsonData.posts;
			for (var i in posts) {
				var tags = posts[i].tags.split(" ");
				for (var i in tags) {
					if (moe.indexOf(moe.currentTags, tags[i]) == -1)
						moe.currentTags.push(tags[i]);
					if (moe.indexOf(moe.taglist, tags[i]) == -1) {
						moe.taglist.push(tags[i]);
						fetchingTags.push(tags[i]);
					}
				}
			}
			if (fetchingTags.length == 0) {
				renderTags({});
			}
			else {
				var url = 'http://' + window.location.host + '/json',
					tags = fetchingTags.join(','),
					data = {
						'action' : 'tagInfo', 
						'tags' : tags
					},
					callback = function(data) {
						renderTags(data.tagInfo);
					};
				if ((url + tags + '&action=tagInfo').length < 2082) {
					$.getJSON(url, data, callback);
				} else {
					$.post(url, data, callback , 'json');
				}
			}
		},
		renderTags = function(tags) {
			$.each(tags, function(k, v) {
				var name = v.name, count = v.count, type = v.type;
				moe.taglist[name] = [count, type];
			});
			var tags = [];
			for (var i in moe.currentTags) {
				var name = moe.currentTags[i];
				moe.currentTags[i] = moe.taglist[name];
				tags.push([name, moe.currentTags[i][0], moe.currentTags[i][1]]);
			}
			moe.currentTags = tags.sort(function(a, b) {return a[1] - b[1]});
			moe.tagTab(99);
		},
		renderPaging = function() {
			var i, html,
			pageHTML = '',
			getHref = function(page) {
				var hash = moe.history.getToken();
				if (page === 'prev') {
					page = moe.jsonData.page.current - 1;
				} else if (page === 'next') {
					page = moe.jsonData.page.current + 1;
				}
				
				if (hash.search(/page=\d+/) != -1) {
					hash = hash.replace(/page=\d+/, 'page=' + page);
				} else {
					hash += '&page=' + page;
				}
				return '#' + hash;
			};
			if (pageData.total > 1) {
				if (pageData.hasPrev) {
					html = '<a class="page-prev" href="' + getHref('prev') + '">&lt;&lt;</a> ';
				} else {
					html = '<span class="disabled">&lt;&lt;</span> ';
				}
				pageHTML += html;
				if (pageData.total <= 10) {
					for (i = 1; i <= pageData.total; i++) {
						if (i === pageData.current) {
							html = '<span class="current">' + pageData.current + '</span> ';
						} else {
							html = '<a href="' + getHref(i) + '">' + i + '</a> ';
						}
						pageHTML += html;
					}
				} else if (pageData.current < 8) {
					for (i = 1; i <= 8; i++) {
						if (i === pageData.current) {
							html = '<span class="current">' + pageData.current + '</span> ';
						} else {
							html = '<a href="' + getHref(i) + '">' + i + '</a> ';
						}
						pageHTML += html;
					}
					html = '<span class="disabled">...</span> <a href="' + getHref(pageData.total) + '">' + pageData.total + '</a> ';
					pageHTML += html;
				} else if(pageData.current > pageData.total - 7) {
					html = '<a href="' + getHref(1) + '">1</a> <span class="disabled">...</span> ';
					pageHTML += html;
					for (i = 7; i >= 0; i--) {
						if (pageData.current === pageData.total - i) {
							html = '<span class="current">' + pageData.current + '</span> ';
						} else {
							html = '<a href="' + getHref(pageData.total - i) + '">' + (pageData.total - i) + '</a> ';
						}
						pageHTML += html;
					}
				} else {
					html = '<a href="' + getHref(1) + '">1</a> <span class="disabled">...</span> ';
					pageHTML += html;
					for (i = -3; i <= 3; i++) {
						if (i === 0) {
							html = '<span class="current">' + pageData.current + '</span> ';
						} else {
							html = '<a href="' + getHref(pageData.current + i) + '">' + (pageData.current + i) + '</a> ';
						}
						pageHTML += html;
					}
					html = '<span class="disabled">...</span> <a href="' + getHref(pageData.total) + '">' + pageData.total + '</a> ';
					pageHTML += html;
				}
				if (pageData.hasNext) {
					html = '<a class="page-next" href="' + getHref('next') + '">&gt;&gt;</a> ';
				} else {
					html = '<span class="disabled">&gt;&gt;</span> ';
				}
				pageHTML += html;
				pageHTML += '<p style="color:#999;margin-top:1em;">(Total: ' + moe.digit_grouping(pageData.posts_total) + ')</p>';
			}
			$page.append(pageHTML);	
			//renderPaging function END
		},
		renderPosts = function() {
			var posts = moe.jsonData.posts,
				$ul = $('<ul></ul>'),
				previewHeight = moe.config.preview_height||150;
			
			for (var i in posts) {
				var post = posts[i],
					title = 'Id: ' + post.id
						+ ' Size: ' + post.width + 'x' + post.height
						+ ' Rating: ' + post.rating
						+ ' Score: ' + post.score
						+ ' File: ' + post.previewUrl.substring(post.previewUrl.lastIndexOf('.') + 1).toUpperCase()
						+ ' Tags: ' + post.tags,
					$li = $('<li></li>', {'class' : 'post-img'}),
					$img = $('<img />', {
							'src' : post.previewUrl,
							'class' : 'viewable',
							'id' : post.id,
							//'width' : post.previewWidth,
							//'height' : post.previewHeight,
							'info' : title
						});
					
					$img
						.load(function(event){
							var $img = $(event.target);
							$img.trigger('resize');
							})
						.resize(function(event){
							var $img = $(event.target),
								$li = $img.parent('li');
							if ($img.height() > $li.height()) {
								$img.height($li.height());
							}
							$('#content-inner').trigger('resize.moe');
						})
						.error(function() {
							var msg, $that = $(this), post = moe.getPostById($that.attr('id'));
							if (post.fileUrl.indexOf('.swf') !== -1) {//flash
								msg = 'Flash';
							} else {
								msg = post.previewUrl + ' Not Found!'
							}
							$that
								.parent()
								.append($('<div></div>', {
									'class' : 'not-found viewable',
									id : post.id,
									width : post.previewWidth,
									height : post.previewHeight,
									title : $that.attr('info')
								}).append(msg))
								.end()
								.remove();
							return true;
						});
					
				$li.height(previewHeight).append($img);
				$ul.append($li).appendTo($posts);
				/*
				* In some brower, already cache of images doesn't trigger onload event
				*/
				$img.trigger('resize');
			}
			//renderPosts function END
		},
		poolsEventBind = function() {
			var getPoolById = function(id) {
					var pools = moe.jsonData.pools,
						result;
					if (!pools) {
						return null;
					}
					for (var i in pools) {
						if (id == pools[i].id) {
							result = pools[i];
							break;
						}
					}
					return result;
				},
				getThumbImage = function(id) {
					var pool = getPoolById(id),
						post, $img, $link;
					if (!pool.posts || pool.posts.length < 1) {
						return null;
					}
					post = pool.posts[0];
					$img = $('<img />', {'src' : post.previewUrl});
					$link = $('<a></a>', {'href' : './#action=listPoolPosts&id=' + id})
						.css('display', 'block')
						.append($img)
						.click(function() {
							$('.navigation a.selected').attr('href', window.location.hash);
						});
					return $link;
				},
				preload = function() {
					var pools = moe.jsonData.pools,
						$preloadDiv = $('<div></div>');
					for (var i in pools) {
						var pool = pools[i];
						if (!pool.posts || pool.posts.length < 1) {
							continue;
						}
						var url = pool.posts[0].previewUrl;
						$preloadDiv.append($('<img />', {'src' : url}));
					}
					$preloadDiv
						.css('display', 'none')
						.appendTo($('#posts'));
				},
				hideThumb = function() {
					$thumb.hide();
				},
				$table = $('#posts table'),
				$tbody = $table.find('tbody'),
				$thumb = $('<div class="pool-thumb shadow-grey"></div'),
				h_offset = 20, 
				name_col_width_rate = 0.8;
				
				$tbody.find('tr').hover(function(event){
					var $target = $(event.currentTarget),
						id = event.currentTarget.id.substring(1),
						$image = getThumbImage(id);
					if ($image === null) {
						return;
					}
					$thumb
						.empty()
						.append($image)
						.appendTo($('#posts'))
						.show();
					var left = $tbody.width() * name_col_width_rate - $image.width() - h_offset;
					$thumb.css('left', left);
					if ($image.height() >= $tbody.height()) {
						$thumb.css('top', $tbody.position().top);
					} else if ($target.position().top + $image.height() > $table.height()) {
						$thumb.css('top', $table.height() - $image.height());
					} else {
						$thumb.css('top', $target.position().top);
					}
				}, function(event) {
					if ($thumb.has(event.relatedTarget).size() > 0) {
						$thumb.one('mouseout', function(e){
							hideThumb();
						});
						return;
					}
					hideThumb();
				});
				$table.find('a').click(function() {
					$('.navigation a.selected').attr('href', window.location.hash);
				});
				
			preload();
		},
		renderPools = function() {
			var pools = moe.jsonData.pools,
				thead = 
				'<thead>\n' +
					'<tr>\n' +
						'<th width="80%">Name</th>\n' +
						'<th width="*">Posts</th>\n' +
					'</tr>\n' +
				'</thead>\n',
				$tbody = $('<tbody></tbody>'),
				$table = $('<table></table>', {'class' : 'pools-list', 'width' : '100%'});
			
			for (var i in pools) {
				var pool = pools[i];
					clazz = (i % 2 == 0) ? 'even' : 'odd',
					row = 
						'<tr class="' + clazz + ' pool-row" id="p' + pool.id + '">\n' +
							'<td><a href="./#action=listPoolPosts&id=' + pool.id + '">' + pool.name.replace(/_/g, ' ') + '</a></td>\n' +
							'<td>' + pool.count + '</td>\n' +
						'</tr>\n';
				$tbody.append(row);
			}
			$table
				.append(thead)
				.append($tbody)
				.appendTo($posts);
			poolsEventBind();
			//renderPools function END
		}, 
		renderPoolHeader = function() {
			var pool = moe.jsonData.pool,
				$header = $('<div class="pool-header"></div>');
			$header.append('<h4>Pool(' + pool.id + '): ' + pool.name.replace(/_/g, ' ') + '</h4>');
			if (pool.description != '') {
				var des = pool.description,
					re = /<<([^<>]*)>>/g,
					arr;
				while(arr = re.exec(des)) {
					var tmp = arr[1].split('|'),
						link = '<a href="' + tmp[0] + '" target="_blank">' + tmp[1] + '</a>';
					des = des.replace(/<<([^<>]*)>>/, link);
				}
				$header.append('<p>' + des + '</p>');
			}
			$posts.append($header);
			var $newPosts = $('<div></div>');
			$newPosts.css('position', 'relative');
			$posts.append($newPosts);
			$posts = $newPosts;
			//renderPoolHeader function END
		},
		data = moe.jsonData;
	
	if (!moe.jsonData) {//not data?!
		return;
	}
	//clear
	$posts.find('*')
		.empty()
		.remove();
	$page.find('*')
		.empty()
		.remove();
	//render
	if (data.pools) {
		if (data.pools.length < 1) {
			$posts.append('<p>╮(﹀_﹀")╭Does not have pools!</p>');
		} else {
			prepareTags();
			renderPools();
			renderPaging();
		}
	} else if (data.posts.length < 1) {//query result is 0
		$posts.append('<p>╮(﹀_﹀")╭Does not have post!</p>');
	} else {
		if (data.pool) {
			renderPoolHeader();
		}
		prepareTags();
		renderPosts();
		renderPaging();
	}
	
	$('#content-inner').trigger('resize.moe');
	//renderContent function end
},
/*
 * previewLayout
 * @Deprecated
 */
previewLayout : (function() {
	var LocatorStack = function() {
			var that = {},
				stack = [],
				maxHeight = 0;
				
			that._stack = stack;
			
			that.add = function(locator) {
				stack.push(locator);
				stack.sort(function(a, b) {
					if (a.getY() > b.getY()) {
						return -1;
					} else if (a.getY() < b.getY()) {
						return 1;
					} else if (a.getX() > b.getX()) {
						return -1;
					} else if (a.getX() < b.getX()) {
						return 1;
					} else {
						return 0;
					}
				});
				maxHeight = Math.max(maxHeight, locator.getY());
			};
			that.get = function() {
				return stack.pop()
			};
			that.isEmpty = function() {
				return stack.length === 0;
			};
			that.collide = function(x, y, width, height) {
				$.each(stack, function(i, n) {
					n.collide(x, y, width, height);
				});
			};
			that.each = function(callback) {
				$.each(stack, callback);
			};
			that.getMaxHeight = function() {
				return maxHeight;
			};
			return that;
		},
		Locator = function(x, y, width, height) {
			var that = {},
				collide = false;
				
			height = height || 0;
				
			that.x = x;
			that.y = y;
			that.width = width;
			that.height = height;
			that._collide = collide;
			
			that.getX = function() {
				return this.x;
			};
			that.getY = function() {
				return this.y;
			};
			that.getWidth = function() {
				return this.width;
			};
			that.getHeight = function() {
				return this.height;
			};
			that.fit = function(e) {
				if (this._collide) {
					return false;
				}
				var w = Math.floor($(e).outerWidth(true));
				return this.width >= w;
			};
			that.collide = function(referX, referY, referWidth, referHeight) {
				if (this.x  < referX && this.x + this.width > referX && referY + referHeight > this.y) {
					this.width = referX - this.x;
					this.height = referY + referHeight;
				} else if (this.x > referX && this.x < referX + referWidth && this.y > referY && this.y < referY + referHeight) {
					this._collide = true;
					this.height = 0;
				} else if (this.x > referX && this.x < referX + referWidth && this.y === referY) {
					this._collide = true;
					this.height = 0;
				} else if (this.x === referX && this.y === referY) {
					this._collide = true;
					this.height = 0;
				}
			};
			that.desert = function(containerWidth) {
				if (this.height > 0) {
					return Locator(this.x, this.height, containerWidth - this.x);
				}
				return null;
			};
			return that;
		},
		ElementStack = function() {
			var that = {},
				stack = [];
				
			that._stack = stack;
			
			that.add = function(e) {
				stack.push(e);
				if (stack.length < 2) {
					return;
				}
				stack.sort(function(a, b) {
					var $a = $(a), $b = $(b);
					
					if (Math.floor($a.outerWidth(true)) > Math.floor($b.outerWidth(true))) {
						return -1;
					} else if (Math.floor($a.outerWidth(true)) < Math.floor($b.outerWidth(true))) {
						return 1;
					} else if (Math.floor($a.outerHeight(true)) > Math.floor($b.outerHeight(true))) {
						return 1;
					} else if (Math.floor($a.outerHeight(true)) < Math.floor($b.outerHeight(true))) {
						return -1;
					} else {
						return 0;
					}
				});
			};
			that.get = function(i) {
				return stack.splice(i, 1)[0];
			};
			that.isEmpty = function() {
				return stack.length === 0;
			};
			that.iterator = function() {
				return stack;
			};
			return that;
		},
		LinkedList = function() {
			var that = {},
				head = null,
				end = null;
			head = end = {'item' : null, 'next' : null};
			
			//that._head = head;
			//that._end = end;
			
			that.add = function(e) {
				end.next = {
					'item' : e,
					'next' : null
				};
				end = end.next;
			};
			that.addAll = function(c) {
				for (var i in c) {
					this.add(c[i]);
				}
			};
			that.get = function(index) {
				var prev = head, cur = prev.next;
				while(index-- > 0) {
					prev = prev.next;
					cur = cur.next;
				}
				prev.next = cur.next;
				return cur.item;
			};
			that.isEmpty = function() {
				return head.next === null;
			};
			that.iterator = function() {
				var result = [], cur = head;
				while((cur = cur.next) !== null) {
					result.push(cur.item);
				}
				return result;
			};
			return that;
		};
		
	/*
	 * previewLayout function body
	 */
	return function($container, $items) {
		var elementStack = LinkedList(),
			locatorStack = LocatorStack();
			
		if ($items.size() < 1) {
			return;
		}
		$items.each(function(i) {
			elementStack.add(this);
		});
		//init locator
		locatorStack.add(Locator(0, 0, Math.floor($container.width()), 0));
		
		var locator, iterator, i, element, fit;
		//layout
		while(!elementStack.isEmpty()) {
			locator = locatorStack.get();
			iterator = elementStack.iterator();
			
			//find fit element
			fit = false;
			for(i in iterator) {
				if (locator.fit(iterator[i])) {
					fit = true;
					break;
				}
			}
			if (!fit) {//generate new location
				locator = locator.desert(Math.floor($container.width()));
				if (locator) {
					locatorStack.each(function(i, n) {
						locator.collide(n.getX(), n.getY(), n.getWidth(), 0);
					});
					locatorStack.add(locator);
				}
				continue;
			}
			element = elementStack.get(i);
			$(element)
				.css('position', 'absolute')
				.animate({
					'left' : locator.getX(),
					'top' : locator.getY()
				}, {
					duration : 'slow',
					easing : 'swing'//swing
				});
			//.find('img')
			//.attr('title', Math.floor($(element).outerWidth(true)) + ' / ' + locator.getWidth() + ' | ' + Math.floor($(element).outerHeight(true)) + ' / ' + locator.getHeight());
			
			locatorStack.collide(locator.getX(), locator.getY(), Math.floor($(element).outerWidth(true)), Math.floor($(element).outerHeight(true)));
			
			//generate new location
			if (Math.floor($(element).outerWidth(true)) < locator.getWidth()) {
				locatorStack.add(Locator(locator.getX() + Math.floor($(element).outerWidth(true)), locator.getY(), locator.getWidth() - Math.floor($(element).outerWidth(true)), locator.getHeight()));
			}
			if (Math.floor($(element).outerHeight(true)) < locator.getHeight()) {
				locatorStack.add(Locator(locator.getX(), locator.getY() + Math.floor($(element).outerHeight(true)), locator.getWidth(), locator.getHeight()));
			} else {
				locatorStack.add(Locator(locator.getX(), locator.getY() + Math.floor($(element).outerHeight(true)), Math.floor($container.width()) - locator.getX(), 0));
			}
		}
		//calculate container height
		$container.height(locatorStack.getMaxHeight());
	};
	//previewLayout function end
})(),
/*
 * bindEvent
 *
 */
bindEvent : function() {
	/*
	 * bind page link
	 */
	$('#pagination a').live('click', function() {
		//var hash = $(this).attr('href');
		//moe.loadContent(hash.substring(1));
		window.location.hash = $(this).attr('href');
		$(document).scrollTop(0);
		return false;
	});
	
	/*
	 * navigation area link
	 */
	$('.navigation a').click(function() {
		var $this = $(this), 
			that = this,
			href = '#action=listPosts';
		$('.navigation a').each(function() {
			var $this = $(this);
			if ($this.hasClass('selected') && that !== this) {
				$this.attr('href', window.location.hash);
				$this.removeClass('selected');
				return false;
			}
		});
		
		$this.addClass('selected');
		if ($this.text() === 'Pool') {
			href = '#action=listPools';
		} else if ($this.text() === 'Collection') {
			href = '#action=listCollections';
		}
		window.setTimeout(function() {
			$this.attr('href', href);
		}, 1000);
		$this.blur();
	});
	
	/*
	 * arrow key navigation
	 */
	$(document)
		.bind('keydown', function(event) {
			if ($('#image-viewer').dialog('isOpen')) {
				return;
			}
			if (event.which === 37) {//left arrow
				$('#pagination a.page-prev').click();
				return false;
			} else if (event.which === 39) {//right arrow
				$('#pagination a.page-next').click();
				return false;
			}
		});

	/*
	 * reset #tag-sidebar height
	 */
	$('#content-inner').bind('resize.moe', function() {
		var contentHeight = $('#content').outerHeight(true) - $('#pagination').outerHeight(true),
			windowHeight = $(window).height() - $('.navigation').outerHeight(true) - 18,
			upperHeight = $('#search').outerHeight(true) + $('#tag-toggle').outerHeight(true),
			referHeight = contentHeight > windowHeight ? contentHeight : windowHeight,
			tagSidebarHeight = referHeight - upperHeight;
		tagSidebarHeight = tagSidebarHeight < 100 ? 100 : tagSidebarHeight;
		$('#tag-sidebar').height(tagSidebarHeight);
	});
	/*
	 * #tag-sidebar scroll bar auto hidden
	 */
	$('#tag-sidebar').hover(function(){
		$(this).css('overflow', 'auto');
	}, function(){
		$(this).css('overflow', 'hidden');
	});
	
	/*
	 * bind ajax error
	 */
	$(document).ajaxError(function(event, request, settings, error) {
		//moe.notice.msg('Error requesting page: ' + settings.url);
		moe.notice.msg('Error requesting page: ' + settings.url + '</br>1:' + request.responseText + '</br>2:' + error);
		moe.overlay.destroy();
	});
},
/*
 * loadContent
 *
 */
loadContent : (function() {
	var defaultCallback = function(data) {
			moe.overlay.destroy();
		},
		loadChildrenCount = function() {
			if (!moe.jsonData.posts) {
				return;
			}
			var posts = moe.jsonData.posts,
				ids = [];
			for (var i in posts) {
				var post = posts[i];
				if (post.hasChildren) {
					ids.push(post.id);
				}
			}
			if (ids.length < 1) {
				return;
			}
			var url = 'http://' + window.location.host + '/json',
				id = ids.join(','),
				data = {
					'action' : 'takeChildrenCount', 
					'id' : id
				},
				callback = function(data) {
					moe.childrenCount = data;
				};
			if ((url + id + '&action=takeChildrenCount').length < 2082) {
				$.getJSON(url, data, callback);
			} else {
				$.post(url, data, callback , 'json');
			}
		};
	return function(query, callback) {
		//log('Query: ' + query);
		var url = 'http://' + window.location.host + '/json?' + query;
		if (!callback) {
			callback = defaultCallback;
			moe.overlay.create('#content-inner');
		}
		$.getJSON(url, function(data) {
			moe.history.newItem(query, false);
			
			moe.jsonData = data;
			
			loadChildrenCount();
			
			callback(data);
			
			moe.renderContent();
		});
	}
	//loadContent function end
})(),
/*
 * onload
 *
 */
onload : function() {
	var hashChanged = function(token) {
			if (token === '') {
				token = 'action=listPosts';
			}
			moe.loadContent(token);
			selectHead(token);
			setParam(token);
		},
		setParam = function(hash) {
			var query = hash.split('&'), 
				form = document.getElementById('search_form'),
				formElements = {};
			form.reset();
			for (var i = 0; i < form.length; i++) {
				formElements[form[i].name] = form[i];
			}
			for (var i in query) {
				var pair = query[i].split('='),
					name = decodeURIComponent(pair[0]),
					value = decodeURIComponent(pair[1]);
				if (name === 'action' && value.indexOf('search') === -1) {
					formElements['action'].value = value;
					if (value === 'listPoolPosts') {
						var id = /id=(\d+)/.exec(hash);
						if (id != null) {
							id = id[1];
							formElements['pool'].value = id;
						}
					}
					return;
				}
				if (name in formElements) {
					if ((name + '_operate') in formElements) {
						i = value.indexOf(' ');
						formElements[name + '_operate'].value = value.substring(0, i);
						value = value.substring(i + 1);
					}
					if (name === 'has_children') {
						formElements[name].checked = true;
					} else {
						formElements[name].value = value;
					}
				} else if ((name + '_1') in formElements) {
					var operate, operand;
					if (name === 'tags') {
						if (value.charAt(0) !== 'n') {
							operate = formElements[name + '_operate_1'];
							operand = formElements[name + '_1'];
						} else {
							operate = formElements[name + '_operate_2'];
							operand = formElements[name + '_2'];
						}
					} else if (formElements[name + '_1'].value === '') {
						operate = formElements[name + '_operate_1'];
						operand = formElements[name + '_1'];
					} else {
						operate = formElements[name + '_operate_2'];
						operand = formElements[name + '_2'];
					}
					i = value.indexOf(' ');
					operate.value = value.substring(0, i);
					operand.value = value.substring(i + 1);
				}
			}
		},
		selectHead = function(token) {
			var $heads = $('.navigation a'), 
				searchAction = 'searchPosts',
				collectAction = 'collectPost',
				deleteAction = null,
				index = 0;
			$heads.each(function() {
				$(this).removeClass('selected');
			});
			if (/action=[^$]+Pool/.test(token)) {
				index = 1;
			} else if (/action=[^$]+Collections/.test(token)) {
				index = 2;
				searchAction = 'searchCollections';
				collectAction = 'collectCollectionsPost';
				deleteAction = 'deleteCollection';
			}
			$heads.eq(index).addClass('selected');
			moe.searchAction = searchAction;
			moe.collectAction = collectAction;
			moe.deleteAction = deleteAction;
		};
	moe.history.init();
	moe.history.addHistoryChangeHandler(hashChanged);
	var token = moe.history.getDecodedFragment();
	hashChanged(token);
},
/*
 * loadConfig
 *
 */
loadConfig : function() {
	$.ajax({
		async: false,
		url: 'http://' + window.location.host + '/json?action=config',
		success: function(data, textStatus, jqXHR) {
			moe.config = data;
			if (data.hasCollection) {
				$('.navigation ul').append('<li><a href="./#action=listCollections">Collection</a></li>');
			}
			if (data.hasOther) {
				$('.navigation ul').append('<li><a href="./#action=listOthers">Other</a></li>');
			}
		}
	});
},
/*
seting : (function() {
	
	return function() {
		
	};
})(),
*/
/*
 * overlay objcet
 *
 */
overlay : (function(){
	var that = {},
		target;
	
	that.create = function(obj) {
		if (target) {
			return;
		}
		if (!this.instance) {
			this.instance = $('<div></div>', {
					'class' : 'ui-widget-overlay'
				})
				.css({
					'z-index': 100,
					'position' : 'absolute'
				})
				.append($('<div></div>', {
					'class' : 'loading',
					width : '100%',
					height : '100%'
				}));
			$(window).resize(function() {
				that.resize();
			});
		}
		if (obj instanceof jQuery) {
			target = obj;
		} else {
			target = $(obj);
		}
		this.instance
			.appendTo(target)
			.offset({
				top : target.offset().top,
				left : target.offset().left
			})
			.width(target.outerWidth())
			.height(target.outerHeight());
		target.bind('resize.overlay', function() {
			that.resize();
		})
	};
	that.destroy = function() {
		if (!this.instance || !target) {
			return;
		}
		this.instance.detach();
		target.unbind('overlay');
		target = null;
	};
	that.resize = function() {
		if (!this.instance || !target) {
			return;
		}
		this.instance
			.offset({
				top : target.offset().top,
				left : target.offset().left
			})
			.width(target.outerWidth())
			.height(target.outerHeight());
	};
	return that;
})(),
/*
 * notice object
 *
 */
notice : (function() {
	var that = {},
		$notice,
		timeout,
		cancelTimeout = function() {
			if (timeout) {
				clearTimeout(timeout);
			}
			timeout = null;
		},
		init = function() {
			$notice = $('#notice');
			
			$('#notice > a').hover(function() {
				$(this).toggleClass('ui-state-hover');
			}, function() {
				$(this).toggleClass('ui-state-hover');
			})
			.click(function() {
				cancelTimeout();
				$notice.hide('normal');
				return false;
			});
			
			$notice.hover(function() {
				cancelTimeout();
			}, function() {
				if (!timeout) {
					timeout = setTimeout(function() {
						$notice.hide('normal');
					}, 5000);
				}
			});
		};
	
	that.msg = function(msg) {
		if (!$notice) {
			init();
		}
		cancelTimeout();
		$('#notice > div').html(msg);
		$notice
			.hide()
			.css({
				'display' : 'block',
				'top' : $(window).height(),
				'left' : $(window).width() - $notice.outerWidth()
			})
			.animate({
				'top' : $(window).height() - $notice.outerHeight()
			}, {
				duration : 'slow',
				complete : function() {
					timeout = setTimeout(function() {
						$notice.hide('normal');
					}, 5000);
				}
			});
	};
	return that;
})(),
/*
 * init
 *
 */
init : function() {
	moe.loadConfig();
	moe.bindEvent();
	moe.onload();
	moe.initSidebar();
	moe.initSidebarSlip();
	moe.initPreview();
	moe.initImageViewer();
	
	moe.cssHack();
}

//moe defined end
};

/*
 * document onload
 *
 */
$(function() {
	moe.history = window.ajaxHistory;
	moe.init();
});

/***test**/
function log(msg) {
	/*
	var $nav = $('.navigation');
	$nav.html($nav.html() + '|' + msg);
	*/
	//console.log(msg);
}

/*****/